#include <avr/io.h>
#include <avr/interrupt.h>
#include <compat/deprecated.h> 

#include <string.h>  
#include <stdio.h> 

#include "BuffFifo.h"
#include "key.h"
#include "mail.h"


#define KEY_IN_0_PORT 	PORTD
#define KEY_IN_1_PORT 	PORTD
#define KEY_IN_2_PORT 	PORTD

#define KEY_IN_0_PIN  	PIND
#define KEY_IN_1_PIN  	PIND
#define KEY_IN_2_PIN  	PIND

#define KEY_IN_0_DIR  	DDRD
#define KEY_IN_1_DIR  	DDRD
#define KEY_IN_2_DIR  	DDRD

#define KEY_IN_0		2
#define KEY_IN_1		3
#define KEY_IN_2		4

#define KEY_NULL	0
#define KEY_DOWN	1
#define KEY_UP 		2
#define KEY_HOLD    3

#define KEY_UP_DOWN_COUNT   10
#define KEY_UP_COUNT 		10
#define KEY_HOLD_COUNT    	100

#define KEYIN_MSG_BUF 15
BUFF_DECL_FIFO(KeyInSerialMsgBuf,(KEYIN_MSG_BUF*3));

#define KEYIN_MANAGE_BUFF 10 
BUFF_DECL_FIFO(KeyInManageMsgBuf,KEYIN_MANAGE_BUFF);


void KeyInManageMsgSend(unsigned char);

struct SKeyInData
{
    unsigned char key_code;
    unsigned char key_up;
    unsigned char key_dw;
} sKeyData[3] = {{KEY_NULL,KEY_NULL,KEY_DOWN}
							,{KEY_NULL,KEY_NULL,KEY_DOWN}
							,{KEY_NULL,KEY_NULL,KEY_DOWN}};


#define TIME_KEYIN_INTERVAL 10
unsigned int time_keyin; 
unsigned int time_keyin_task;


static volatile unsigned char sleep_activated = FALSE;
static volatile unsigned char keyin_interrup_activated = FALSE;

static volatile unsigned int interrup_count=0;

ISR(INT0_vect)
{	
	interrup_count++; 
	keyin_interrup_activated = TRUE;
	
	cbi(GIFR,INTF0);	
	
}


ISR(INT1_vect)
{
	//cbi(GIFR,INTF1);	
	interrup_count++;
}


void SetKeyInterrup(unsigned char enable)
{

	if(enable == TRUE)
	{
		//INT0: External Interrupt Request 1 enable
		sbi(GICR,INT0); 		
	}
	else
	{
		//INT0: External Interrupt Request 1 disable
		cbi(GICR,INT0); 
	}

}
							
void InitKeyIn( void )
{

	cbi(KEY_IN_0_PORT, KEY_IN_0);
	cbi(KEY_IN_0_DIR,  KEY_IN_0);
	
	cbi(KEY_IN_1_PORT, KEY_IN_1);
	cbi(KEY_IN_1_DIR,  KEY_IN_0);
	
	cbi(KEY_IN_2_PORT, KEY_IN_2);
	cbi(KEY_IN_2_DIR,  KEY_IN_2);
			
	cbi(MCUCR,ISC00); 
	cbi(MCUCR,ISC01);
	
	cbi(MCUCR,ISC10); 
	cbi(MCUCR,ISC11);

	//INT0: External Interrupt Request 1 disable
	cbi(GICR,INT0); 
	
	//INT1: External Interrupt Request 1 Enable
	//sbi(GICR,INT1);
	
	
	time_keyin = TIME_KEYIN_INTERVAL;
	time_keyin_task = 10;
	
	BUFF_INIT_FIFO(KeyInSerialMsgBuf);
	BUFF_INIT_FIFO(KeyInManageMsgBuf);
	
}


//10ms time interval
void TimeKeyIn( void )
{
	if(time_keyin > 0)
	{
		time_keyin--;
		if(time_keyin==0)
		{		
			if(time_keyin_task>0)
			{
				time_keyin_task--;
			}
			time_keyin = TIME_KEYIN_INTERVAL;
		}
	}
}

void KeyInSerialMsgSend(char *ptr, unsigned char size)
{

	// unsigned char i;
	
	// for(i=0;i<size;i++)
	// {
		// if( BuffPutFifo(KeyInSerialMsgBuf,*ptr++) == FIFO_ERR)
		// {
			// break;
		// }
	// }
	// SendMailFifo(SERIAL_DEV,0x01,size,(char *)KeyInSerialMsgBuf);

}

void KeyInManageMsgSend(unsigned char key_code)
{

	printf("K%d\r\n",key_code);
	
	if( BuffPutFifo(KeyInManageMsgBuf,key_code) == FIFO_ERR)
	{
		BUFF_INIT_FIFO(KeyInManageMsgBuf);
		return;
	}

	SendMailFifo(MANAGE_DEV,0x02,1,(char *)KeyInManageMsgBuf);
	
}



void KeyInMail(unsigned char act, unsigned char size, char * pbuf)
{

	if(act == 0x01)
	{
		sleep_activated = BuffPullFifo((psBufFifo)pbuf);
		//SetKeyInterrup(enabel);
	}
	
	
}

void doIncKeyIn(struct SKeyInData * pKeyIn)
{
	if( pKeyIn->key_up < KEY_HOLD_COUNT )	
	{
		pKeyIn->key_up += 1;
		if( pKeyIn->key_up == KEY_UP_COUNT )
		{
			pKeyIn->key_code = KEY_UP;
			pKeyIn->key_dw = 0;
		}
		else if( pKeyIn->key_up == KEY_HOLD_COUNT )	
		{
			pKeyIn->key_code  = KEY_HOLD;			
			pKeyIn->key_dw = 0;
		}
	}	
}

void doDecKeyIn(struct SKeyInData * pKeyIn)
{
	if( pKeyIn->key_dw < KEY_UP_DOWN_COUNT )	
	{
		pKeyIn->key_dw += 1;
		if( pKeyIn->key_dw == KEY_UP_DOWN_COUNT )
		{			
			if( pKeyIn->key_up >= KEY_UP_COUNT )
			{
				pKeyIn->key_code = KEY_DOWN;
				pKeyIn->key_up = 0;			
			}
			else
				pKeyIn->key_code = KEY_NULL;
		}
	}	
}


void doKeyDetect(void)
{
	if( bit_is_clear(KEY_IN_0_PIN,KEY_IN_0) )
		doIncKeyIn(&sKeyData[0]);
	else
		doDecKeyIn(&sKeyData[0]);	
		
	if( bit_is_clear(KEY_IN_1_PIN,KEY_IN_1) )
		doIncKeyIn(&sKeyData[1]);
	else
		doDecKeyIn(&sKeyData[1]);	

	if( bit_is_clear(KEY_IN_2_PIN,KEY_IN_2) )
		doIncKeyIn(&sKeyData[2]);
	else
		doDecKeyIn(&sKeyData[2]);		
}

void doKeyEncode(unsigned char key_mode)
{
	char sKeyInMsgBuf[KEYIN_MSG_BUF];
	
	if( sKeyData[key_mode].key_code == KEY_UP)
	{
		sprintf((char *)&sKeyInMsgBuf,"Key-%d-Up\r\n",key_mode);	

		KeyInSerialMsgSend((char *)&sKeyInMsgBuf,strlen((const char *)&sKeyInMsgBuf));
		
		KeyInManageMsgSend(((key_mode << 4) & 0xF0) + 1); //0xX1
		
		sKeyData[key_mode].key_code = KEY_NULL;						
		
		
	}	
	else if( sKeyData[key_mode].key_code == KEY_DOWN)
	{
		sprintf((char *)&sKeyInMsgBuf,"Key-%d-Down\r\n",key_mode);		

		KeyInSerialMsgSend((char *)&sKeyInMsgBuf,strlen((const char *)&sKeyInMsgBuf));		
		
		KeyInManageMsgSend(((key_mode << 4) & 0xF0) + 2); //0xX2
		
		sKeyData[key_mode].key_code = KEY_NULL;			
				
	}
	else if( sKeyData[key_mode].key_code == KEY_HOLD)
	{		
		sprintf((char *)&sKeyInMsgBuf,"Key-%d-Hold\r\n",key_mode);

		KeyInSerialMsgSend((char *)&sKeyInMsgBuf,strlen((const char *)&sKeyInMsgBuf));			

		KeyInManageMsgSend(((key_mode << 4) & 0xF0) + 3); //0xX3
		
		sKeyData[key_mode].key_code = KEY_NULL;						
	
	}
}

unsigned char keyin_mode = 0;
unsigned char key_wakeup_activate = FALSE;
void KeyInTask( void )
{
	if(time_keyin_task==0)
	{
		time_keyin_task = 1;
		
		doKeyDetect();
		
		doKeyEncode(keyin_mode);
		keyin_mode++;
		if( keyin_mode > 2)
		{
			keyin_mode = 0;
		}

		SetKeyInterrup( sleep_activated );		
				
	}			
	
	if( sleep_activated == TRUE )
	{
		if( keyin_interrup_activated == TRUE && key_wakeup_activate == FALSE)
		{
			KeyInManageMsgSend( KEY_OFF );	
			key_wakeup_activate = TRUE;
		}		
		keyin_interrup_activated = FALSE;		
	}
	else
	{
		key_wakeup_activate = FALSE;
		keyin_interrup_activated = FALSE;
	}
	
}
